#ifndef VECTOR_BATCH_H
#define VECTOR_BATCH_H

#include "Vector2.h"
#include "Colors.h"
#include "Renderer.h"

namespace Cvekas {

/// Represents triangle, atomic component of any vector graphics shape.
/// For internal use.
struct Triangle
{
	/// Constructor
	Triangle();

	/// Copy constructor
	Triangle(const Triangle& t);

	/// Sort operator
	bool operator<(const Triangle& t);

	Vector2 p1, p2, p3;
	Color color;
	int layer;
};

/// Interval of triangles with same texture and layer. For internal use.
struct TriangleSpan
{
	uint first, count;
};

/// Allows to easily draw line segments and flat polygons.
class VectorBatch: public Renderable, public boost::noncopyable
{
public:
	/// Constructor
	/// \param renderer Renderer to which this %VectorBatch instance will send batches
	/// \param virtual_width Virtual resolution width
	/// \param virtual_height Virtual resolution height
	/// \param base_priority Base priority value of generated batches.
	/// Individual priority for each batch is calculated like this: base_priority + layer
	VectorBatch(RendererPtr renderer, uint virtual_width, uint virtual_height, uint16 base_priority = 1000);

	/// Destructor
	~VectorBatch();

	/// Prepares batches and registers for rendering. Must be called after all drawing in current frame is done.
	void present();

	/// Sets new effect. Default effect is provided, so it is not required to set it.
	/// Default effect is named %VectorGraphics and is loaded from file default_effect_file
	void setEffect(EffectPtr effect);

	/// Draws a line segment
	void drawLine(uint layer, const Vector2& start, const Vector2& end, float width = 1.0f, 
		const Color& color = Color(255, 255, 255, 255));

	/// Draws a strip of lines
	void drawLineStrip(uint layer, const std::vector<Vector2>& points, float width = 1.0f, 
		const Color& color = Color(255, 255, 255, 255));

	/// Draws a triangle
	void drawTriangle(uint layer, const Vector2& p1, const Vector2& p2, const Vector2& p3, 
		const Color& color = Color(255, 255, 255, 255));

	/// Draws a polygon
	/// \param points Polygon vertices, ordered clockwise
	void drawPolygon(uint layer, const std::vector<Vector2>& points, const Color& color = Color(255, 255, 255, 255));

	/// Sets new virtual resolution
	void setVirtualResolution(uint width, uint height) { virtual_width = width; virtual_height = height; };

	// Renderable implementation
	virtual void onPreRender(uint16 batch_id);
	virtual uint getBatches(Batch** batches);

private:
	void build_batches();

	static const uint max_triangles = 4096;
	static const uint max_spans = 512;

	RendererPtr renderer;
	EffectPtr effect;

	VertexBufferPtr vertex_buffer;

	static int vertex_buffer_name_counter;
	
	boost::array<Triangle, max_triangles> triangles;
	boost::array<TriangleSpan, max_spans> spans;
	boost::array<Batch, max_spans> batches;

	uint triangle_count, span_count, virtual_width, virtual_height;
	uint16 base_priority;
	
	bool presented;
};

typedef boost::shared_ptr<VectorBatch> VectorBatchPtr;

} // namespace

#endif